/* 
 * File:   V4LInterface.hpp
 * Author: gustavo
 *
 * Created on August 30, 2012, 5:13 AM
 */

#ifndef V4LINTERFACE_HPP
#define	V4LINTERFACE_HPP

#include <gtkmm.h>
#include <gtkmm/box.h>


#include "../../capture/v4l_capture.hpp"

namespace imp {
	namespace gui {

		class V4LInterface : public Gtk::VBox {
			/////
		private:
			//==================================================================
			capture::V4LCapture v4lcap;

			//==================================================================
			Gtk::Frame frm_device_info;
			Gtk::ComboBoxText cb_device;
			Gtk::Button bt_start;
			//-------------------------------
			Gtk::Label lb_device_name;
			Gtk::Label lb_device_card;
			Gtk::Label lb_device_driver;
			Gtk::Label lb_device_bus;

			//==================================================================
			Gtk::Frame frm_device_prop;
			Gtk::SpinButton sp_width;
			Gtk::SpinButton sp_height;

			//==================================================================
			Gtk::ComboBox cb_input;
			Gtk::ComboBox cb_standard;
			Gtk::ComboBox cb_format_desc;
			Gtk::ComboBox cb_frame_size;
			//----------------------------------
			Glib::RefPtr<Gtk::ListStore> ls_input;
			Glib::RefPtr<Gtk::ListStore> ls_standard;
			Glib::RefPtr<Gtk::ListStore> ls_format_desc;
			Glib::RefPtr<Gtk::ListStore> ls_frmsize;
			//----------------------------------

			template <class T> class ModelColumn : public Gtk::TreeModel::ColumnRecord {
			public:

				ModelColumn() {
					add(m_col_name);
					add(m_col_data);
				}

				Gtk::TreeModelColumn<Glib::ustring> m_col_name;
				Gtk::TreeModelColumn<T> m_col_data;
			};
			typedef ModelColumn<struct v4l2_input> ModelInput;
			typedef ModelColumn<struct v4l2_standard> ModelStandard;
			typedef ModelColumn<struct v4l2_fmtdesc> ModelFormatDesc;
			typedef ModelColumn<struct v4l2_frmsizeenum> ModelFrameSize;
			typedef ModelColumn<struct v4l2_querymenu> ModelControlMenu;

			ModelInput model_input;
			ModelStandard model_standard;
			ModelFormatDesc model_format_desc;
			ModelFrameSize model_frame_size;
			ModelControlMenu model_control_menu;

			//==================================================================
			Gtk::Notebook notebook;

			//==================================================================

		public: /* Constructors */
			V4LInterface();
			virtual ~V4LInterface();

		public: /* Methods */
			capture::V4LCapture& get_v4l_capture();

		private: /* Auxiliary Methods */
			void __init_combo_boxes();
			void __build();
			void __frame_device_conf();
			void __frame_device_prop();

			//==================================================================
			sigc::connection cb_input_signal;
			sigc::connection cb_standard_signal;
			sigc::connection cb_format_desc_signal;
			sigc::connection cb_frmsize_signal;
			void __connect_signals();

			//==================================================================
			void __update_cb_device();
			void __update_cb_input();
			void __update_cb_standard();
			void __update_cb_format_desc();
			void __update_cb_frmsize();
			void __update_capabilities();

			//==================================================================

			typedef struct __ctrl_holder {
				struct v4l2_queryctrl qctrl;
				Gtk::Widget * widget;
				sigc::connection con;
			} ControlHolder;
			std::list< ControlHolder > ctrl_list_default;
			std::list< ControlHolder > ctrl_list_user;
			std::list< ControlHolder > ctrl_list_private;

			void __create_control_lists();
			void __create_default_control_list();
			void __create_user_control_list();
			void __create_private_control_list();
			void __update_control_widgets(std::list< ControlHolder >& list);

			void __block_control_signals(std::list< ControlHolder >& list, bool block);

			void set_control(std::list< ControlHolder > * list, Gtk::Widget * widget);
			bool set_control_hscale(int type, double val, std::list< ControlHolder > * list, Gtk::Widget * wctrl);

			void __make_control_table(std::list< ControlHolder >& list, const char * title);

		private: /* Events */
			void event_bt_start_clicked();
			void event_cb_device_changed();
			void event_cb_input_changed();
			void event_cb_standard_changed();
			void event_cb_format_desc_changed();
			void event_cb_frame_size_changed();

		public: /* Signals */
			typedef sigc::signal<void, bool> SignalStart;

			SignalStart signal_start() {
				return m_signal_start;
			}

		protected:
			SignalStart m_signal_start;


		};
	}
}
#endif	/* V4LINTERFACE_HPP */

